Skip to main content

Constant 和 Immutable 状态变量

共性

  • 合约一旦部署之后,变量将不在修改。
  • 与常规状态变量相比,常量和不可变量的 gas 成本要低得多(作为 gas 优化手段)
  • 不是所有类型的状态变量都支持用 constant 或 immutable 来修饰,当前仅支持 字符串 (仅常量) 和 值类型 .

区别

constant(常量)

  • 对于 constant 常量, 他的值在编译器确定
  • 可以在文件级别定义 constant 变量(注:0.7.2 之后加入的特性)。
  • 编译器不会为这些变量预留存储位,它们的每次出现都会被替换为相应的常量表达式

immutable(不可变量)

  • 对于 immutable, 它的值在部署时确定。

  • 不可变变量在构造时进行一次求值,并将其值复制到代码中访问它们的所有位置。 对于这些值,将保留 32 个字节,即使它们适合较少的字节也是如此。 因此,常量有时可能比不可变量更便宜。

  • 不可变量只能赋值一次,并且在赋值之后才可以读取。

  • 编译器生成的合约创建代码将在返回合约之前修改合约的运行时代码,方法是将对不可变量的所有引用替换为分配给它们的值。

  • 不可变量(Immutable) 是 Solidity 0.6.5 引入的,因此 0.6.5 之前的版本不可用。

    不可变量可以在声明时赋值,不过只有在合约的构造函数执行时才被视为视为初始化。 这意味着,你不能用一个依赖于不可变量的值在行内初始化另一个不可变量。 不过,你可以在合约的构造函数中这样做。

    这是为了防止对状态变量初始化和构造函数顺序的不同解释,特别是继承时,出现问题。

举例:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >0.7.4;
uint constant X = 32**22 + 8;

contract C {

string constant TEXT = "abc";
bytes32 constant MY_HASH = keccak256("abc");
uint immutable decimals;
uint immutable maxBalance;
address immutable owner = msg.sender;

constructor(uint decimals_, address ref) {
decimals = decimals_;
// Assignments to immutables can even access the environment.
maxBalance = ref.balance;
}

function isBalanceTooHigh(address _other) public view returns (bool) {
return _other.balance > maxBalance;
}
}